/******************************************************************
 * Created by: GOH CHEE HONG                                      
 * Date of Creation: 1/Jan/2009     
 * Date of last modification: 
 *                                                                
 * Description: Inbox form that retrieves offline messages from the OpenLookUp network
 * Acknowledgement: Most of the source codes are adopted from the feedexpress
 ******************************************************************/
/*
 * FeedExpress
 * (C) Copyright 2003 Jeppe Cramon (jeppe@cramon.dk)
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Disclaimer:
 * -----------
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied. The entire risk as to the
 * quality and performance of the software is with you. Should the
 * software prove defective, you assume the cost of all necessary
 * servicing, repair, or correction. In no event shall the author,
 * copyright holder, or any other party who may redistribute the
 * software be liable to you for damages, including any general,
 * special, incidental, or consequential damages arising out of
 * the use or inability to use the software (including, but not
 * limited to, loss of data, data being rendered inaccurate, loss of
 * business profits, loss of business information, business
 * interruptions, loss sustained by you or third parties, or a
 * failure of the software to operate with any other software) even
 * if the author, copyright holder, or other party has been advised
 * of the possibility of such damages. 
 * 
 */
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Timers;
using System.Collections;
using Pbdms.Common.BaseClass;
namespace Pbdms.Forms.Views
{
    public partial class FrmInbox : newForms
    {
        private System.Timers.Timer mTimer = new System.Timers.Timer();
        public BusinessLogic.Mail.MailBoxManager MailBoxManager;
        public delegate void DelegateWorker(object sender, EventArgs e);
        public delegate void NoParaDelegateWorker();
        public delegate void individualDelegateWorker(string keyID);
        
        private Pbdms.BusinessLogic.Mail.MailBox ActiveMailbox = null;
        private Pbdms.BusinessLogic.Mail.Message lastMessageView = null;
        private ListViewItem mLastViewedListViewItem = null;
        private Pbdms.Common.ListViewColumnSorter listViewColumnSorter;
        Thread deletingMessage = null;
        public FrmInbox()
        {
            InitializeComponent();

            // setup sorting
            listViewColumnSorter = new Pbdms.Common.ListViewColumnSorter();
            listMessage.ListViewItemSorter = listViewColumnSorter;
            listViewColumnSorter.Order = SortOrder.None;
            listViewColumnSorter.SortColumn = 0;
            listViewColumnSorter.DateColumn = 0;
            listMessage.Sort();
            this.FormClosing += new FormClosingEventHandler(FrmInbox_FormClosing);
            this.listMessage.Click += new EventHandler(listMessage_Click);
            this.listMessage.ColumnClick += new ColumnClickEventHandler(listMessage_ColumnClick);
            this.listMessage.SelectedIndexChanged += new EventHandler(listMessage_SelectedIndexChanged);
            //treeMailbox.AfterSelect += new TreeViewEventHandler(treeMailbox_AfterSelect);
            //treeMailbox.MouseUp += new MouseEventHandler(treeMailbox_MouseUp);

            MailBoxManager = new Pbdms.BusinessLogic.Mail.MailBoxManager(Program.keyControl,Program.publicKeyControl);
            MailBoxManager.NewMessages+= new EventHandler(MailBoxManager_NewMessages);
            MailBoxManager.RefreshDone += new EventHandler(MailBoxManager_RefreshDone);
            MailBoxManager.RefreshStart += new EventHandler(MailBoxManager_RefreshStart);
            
            MailBoxManager.MailBoxAdded += new EventHandler(MailBoxManager_MailBoxAdded);
            
            MailBoxManager.loadMailBoxs();
            Pbdms.Common.Global.paintBackGround(this);
        }
        public override void changeName(string keyID, string oldName, string newName)
        {
            
            lock (this)
            {
                foreach (ListViewItem item in listMessage.Items)
                {
                    ListViewItem.ListViewSubItemCollection subItems = item.SubItems;
                    
                    ListViewItem.ListViewSubItem subItem1 = subItems[1];
                    if (subItem1.Text.Equals(oldName))
                    {
                        subItem1.Text = newName;
                    }
                }
            }
        }
        void listMessage_SelectedIndexChanged(object sender, EventArgs e)
        {
           
			if (listMessage.SelectedItems.Count == 0) {
				return;
			}
			if (listMessage.SelectedItems.Count != 1) {
				
				mLastViewedListViewItem = null;
			} else {
				IEnumerator myEnum = listMessage.SelectedItems.GetEnumerator();
				myEnum.MoveNext();
				ListViewItem viewItem = (ListViewItem)myEnum.Current;
				string messageEntry= (string)viewItem.Tag;
				BusinessLogic.Mail.Message message = (BusinessLogic.Mail.Message) ActiveMailbox.messageManager.messages[messageEntry];
				showMessage(message);
				mLastViewedListViewItem = viewItem;
			}
		

        }

        void listMessage_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == listViewColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (listViewColumnSorter.Order == SortOrder.Ascending)
                {
                    listViewColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    listViewColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                listViewColumnSorter.SortColumn = e.Column;
                listViewColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            this.listMessage.Sort();
        }

        void listMessage_Click(object sender, EventArgs e)
        {
            if (listMessage.SelectedItems.Count == 0)
            {
                return;
            }
            Pbdms.BusinessLogic.Mail.Message message = null;
            foreach (ListViewItem viewItem in listMessage.SelectedItems)
            {
                string messageEntryTag = (string)viewItem.Tag;
                message = (Pbdms.BusinessLogic.Mail.Message)ActiveMailbox.messageManager.messages[messageEntryTag];
                message.isRead = true;
                viewItem.Font = new Font("Tahoma", 8.25f);
                
            }
            showMessage(message);
            if (ActiveMailbox != null)
            {
                //UpdateMailBoxText(ActiveMailbox);
            }

        }
        /// <summary>
        /// method that show context menu
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /*
        void treeMailbox_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                // Select the clicked node
                treeMailbox.SelectedNode = treeMailbox.GetNodeAt(e.X, e.Y);

                if (treeMailbox.SelectedNode != null)
                {
                    if (treeMailbox.SelectedNode.Name.Equals("Outbox"))
                    {
                        RefreshInboxMenu.Visible = false;
                    }
                    else
                    {
                        RefreshInboxMenu.Visible = true;
                    }
                    contextMenu.Show(treeMailbox, e.Location);
                }
            }
        }
         */
        /// <summary>
        /// a method that handle when a form is closing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FrmInbox_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.Hide();
        }
        /// <summary>
        /// when the user select another tree node
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /*
        void treeMailbox_AfterSelect(object sender, TreeViewEventArgs e)
        {
            showMessage(null);
            string tag = e.Node.Name;
            Pbdms.BusinessLogic.Mail.MailBox mailBox = (Pbdms.BusinessLogic.Mail.MailBox)MailBoxManager.MailBoxs[tag];
            showMailBox(mailBox);
        }
         * */
        /// <summary>
        /// method that display the whole mailbox
        /// </summary>
        /// <param name="mailbox"></param>
        void showMailBox(Pbdms.BusinessLogic.Mail.MailBox mailbox)
        {
           // labelTop.Text = mailbox.cacheKey;
            updateListView(mailbox);
        }
        /// <summary>
        /// method that update the display of listview
        /// </summary>
        /// <param name="mailbox"></param>
        void updateListView(Pbdms.BusinessLogic.Mail.MailBox mailbox)
        {
            if (mailbox == null)
            {
                return;
            }
            lock (this)
            {
                Hashtable items = new Hashtable();
               
                foreach (Pbdms.BusinessLogic.Mail.Message message in mailbox.messageManager.messages.Values)
                {
                    ListViewItem listitem = listMessage.Items[message.key];

                    ListViewItem viewItem = new ListViewItem(message.datetime.ToString("r"));
                    if (listitem != null)
                    {
                        viewItem.Checked = listitem.Checked;
                    }
                    viewItem.Tag = message.key;
                    viewItem.Name = message.key;
                    if (message.isRead)
                    {

                        viewItem.Font = new Font("Tahoma", 8.25f);
                    }
                    else
                    {

                        viewItem.Font = new Font("Tahoma", 8.25f, FontStyle.Bold);
                    }
                    string id=BusinessLogic.DataController.BuddyController.create().selectIDBasedOnKeyIDFromDB(message.sender);
                    if (id != null)
                    {
                        Common.DataObject.Buddy buddy = BusinessLogic.DataController.BuddyController.create().selectABuddyBasedOnIDFromDB(id);
                        if (buddy != null)
                        {
                            viewItem.SubItems.Add(buddy.Name);
                        }
                        else
                        {
                            viewItem.SubItems.Add(message.sender);
                        }
                    }
                    else
                    {
                        viewItem.SubItems.Add(message.sender);
                    }
                    viewItem.SubItems.Add(message.subject);

                    items.Add(viewItem.Tag, viewItem);
                }
                listMessage.Items.Clear();
                foreach (ListViewItem item in items.Values)
                {
                    listMessage.Items.Add(item);
                }
                
                listViewColumnSorter.SortColumn = 0;
                listViewColumnSorter.Order = SortOrder.Descending;
                listMessage.Sort();
                ActiveMailbox = mailbox;
            }
        }
        /// <summary>
        /// method that trigger when a mail box is added
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
         
        void MailBoxManager_MailBoxAdded(object sender, EventArgs e)
        {
            /*
            BusinessLogic.Mail.MailBox mailBox=(BusinessLogic.Mail.MailBox) sender;
            TreeNode[] node = treeMailbox.Nodes.Find(mailBox.cacheKey, false);
            treeMailbox_AfterSelect(this,new TreeViewEventArgs(node[0]));
            showMessage(null);
             */
            BusinessLogic.Mail.MailBox mailBox = (BusinessLogic.Mail.MailBox)sender;
            showMailBox(mailBox);
        }
        

        /// <summary>
        /// when a mailbox starts to refresh
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MailBoxManager_RefreshStart(object sender, EventArgs e)
        {
            //invoke GUI thread
            if (InvokeRequired)
            {
                DelegateWorker delegateWorker = new DelegateWorker(MailBoxManager_RefreshStart);
                this.Invoke(delegateWorker, new object[] { sender, e });

            }
            else
            {
                Program.mainForm.toolStripInbox.Text = "Inbox (Refreshing)";
                this.Text = "Inbox (Refreshing)";
            }
        }
        /// <summary>
        /// occurs when the mail box has finished refresh
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void MailBoxManager_RefreshDone(object sender, EventArgs e)
        {
            //invoke GUI thread
            if (InvokeRequired)
            {
                DelegateWorker delegateWorker = new DelegateWorker(MailBoxManager_RefreshDone);
                this.Invoke(delegateWorker, new object[] { sender, e });

            }
            else
            {
                Program.mainForm.toolStripInbox.Text = "Inbox";
                this.Text = "Inbox (Finished refreshing)";
            }
        }
        /// <summary>
        /// method that handle new messages
        /// </summary>
        /// <param name="source"></param>
        /// <param name="args"></param>
        private void MailBoxManager_NewMessages(object source, EventArgs args)
        {
            if (this.InvokeRequired)
            {
                DelegateWorker delegateWorker = new DelegateWorker(MailBoxManager_NewMessages);
                this.Invoke(delegateWorker, new object[] { source, args });
            }
            else
            {
                Pbdms.BusinessLogic.Mail.MailBox mailBox = (Pbdms.BusinessLogic.Mail.MailBox)source;
                updateListView(mailBox);
                //if no node is selected
                /*
                TreeNode node=treeMailbox.SelectedNode;
                if ( node== null) 
                {
                    UpdateMailBoxText(mailBox);
                    return;
                }
                
                Pbdms.BusinessLogic.Mail.MailBox selectedmailBox = (Pbdms.BusinessLogic.Mail.MailBox)MailBoxManager.MailBoxs[node.Name];
                //if the selected node is the one being updated
                
                if (selectedmailBox.cacheKey == mailBox.cacheKey)
                {
                    
                    if (selectedmailBox.messageManager.messages == null)
                    {

                        return;
                    }
                    updateListView(selectedmailBox);
                }
                UpdateMailBoxText(mailBox);
                */
            }
        }
        /// <summary>
        /// method that show individual message
        /// </summary>
        /// <param name="message"></param>
        private void showMessage(Pbdms.BusinessLogic.Mail.Message message)
        {
            Console.WriteLine("before entering message");
            lock (this)
            {


                if (lastMessageView != null)
                {
                    
                    lastMessageView.isRead = true;
                    if (mLastViewedListViewItem != null)
                    {
                        mLastViewedListViewItem.Font = new Font("Tahoma", 8.25f);
                       
                    }
                }
                
                lastMessageView = message;
                //mLastViewedFeed = feed;
                panelFileInfo.Controls.Clear();
                if (message == null)
                {
                    
                    
       
                }
                else 
                {
                    lblDate.Text = message.datetime.ToString("r");
                    //get friend id
                    string id = BusinessLogic.DataController.BuddyController.create().selectIDBasedOnKeyIDFromDB(message.sender);
                    if (id != null)
                    {
                        Common.DataObject.Buddy buddy = BusinessLogic.DataController.BuddyController.create().selectABuddyBasedOnIDFromDB(id);
                        if (buddy != null)
                        {
                            lblFrom.Text = buddy.Name;
                        }
                        else
                        {
                            lblFrom.Text = message.sender;
                        }
                    }
                    else
                    {
                        lblFrom.Text = message.sender;
                    }
                    lblTo.Text = "You";
                    lblSubject.Text = message.subject;
                    if (message.attachments.Count != 0)
                    {
                        foreach (Common.DataObject.OfflineFile offlineFile in message.attachments)
                        {
                            //System.Windows.Forms.LinkLabel label= new LinkLabel();
                            //label.Text=offlineFile.filename;
                            Pbdms.UserControls.FileInfoControl filecontrol = new Pbdms.UserControls.FileInfoControl();
                            filecontrol.setFileName(offlineFile.filename);
                            filecontrol.setSize(Common.Global.GetFileSize(offlineFile.size));
                            filecontrol.Tag = offlineFile;
                            filecontrol.LinkLabelClicked += new EventHandler(filecontrol_LinkLabelClicked);
                            filecontrol.linkRemove.Text = "Download";
                            filecontrol.Dock = DockStyle.Top;
                            panelFileInfo.Controls.Add(filecontrol);
                        }
                    }
                    richMsg.Rtf = message.message;
                }
               
            }
        }

        void filecontrol_LinkLabelClicked(object sender, EventArgs e)
        {
            //open save file dialog
            Pbdms.UserControls.FileInfoControl fileControl= (Pbdms.UserControls.FileInfoControl) sender;
            Common.DataObject.OfflineFile offlineFile= (Pbdms.Common.DataObject.OfflineFile) fileControl.Tag;
            if (checkExists() == false)
            {
                saveFileDia.Title = "Please select the location to save the file";

                DialogResult dlgResult = saveFileDia.ShowDialog();
                string filePath = "";
                if (dlgResult.Equals(DialogResult.OK))
                {
                    filePath = saveFileDia.FileName;
                    Forms.Views.FrmFileDownloading FrmFile = new FrmFileDownloading();
                    FrmFile.setFileToBeDownload(offlineFile, filePath);
                    FrmFile.MdiParent = this.MdiParent;
                    FrmFile.Show();
                }
            }
            else
            {
                MessageBox.Show("Only one active downloading process is allowed.");
            }
           
        }
        private Boolean checkExists()
        {
            Boolean alreadyExist = false;
            foreach (Form frm in (this.MdiParent.MdiChildren))
            {
                frm.WindowState = FormWindowState.Normal;
                if (frm.GetType().Equals(typeof(Pbdms.Forms.Views.FrmFileDownloading)))
                {
                    Pbdms.Forms.Views.FrmFileDownloading checkForm = (Pbdms.Forms.Views.FrmFileDownloading)frm;
                    if (checkForm.finished())
                    {
                        checkForm.Close();
                        alreadyExist = false;
                    }
                    else
                    {
                        alreadyExist = true;
                    }
                    break;
                }
            }
            return alreadyExist;
        }
        /*
        private void UpdateMailBoxText(BusinessLogic.Mail.MailBox mailBox)
        {
            TreeNode[] node = treeMailbox.Nodes.Find(mailBox.cacheKey, false);
            node[0].Text = "[" + mailBox.cacheKey + "] " + mailBox.messageManager.getUnreadCount() + "mails";
        }
        */
        private void RefreshInboxMenu_Click(object sender, EventArgs e)
        {
            MailBoxManager.refreshInbox();
        }
       
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            MailBoxManager.refreshInbox();
        }

        private void btnSelectAll_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                foreach (ListViewItem item in listMessage.Items)
                {
                    item.Checked = true;
                }
            }
        }

        private void btnUnselect_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                foreach (ListViewItem item in listMessage.Items)
                {
                    item.Checked = false;
                }
            }
        }

        private void btnUnread_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                foreach (ListViewItem viewItem in listMessage.CheckedItems)
                {
                    string messageEntryTag = (string)viewItem.Tag;
                    Pbdms.BusinessLogic.Mail.Message message = (Pbdms.BusinessLogic.Mail.Message)ActiveMailbox.messageManager.messages[messageEntryTag];
                    message.isRead = false;
                    viewItem.Font = new Font("Tahoma", 8.25f, FontStyle.Bold);
                    showMessage(message);
                }
            }

            //UpdateMailBoxText(ActiveMailbox);
        }

        private void btnRead_Click(object sender, EventArgs e)
        {
            lock (this)
            {
                foreach (ListViewItem viewItem in listMessage.CheckedItems)
                {
                    string messageEntryTag = (string)viewItem.Tag;
                    Pbdms.BusinessLogic.Mail.Message message = (Pbdms.BusinessLogic.Mail.Message)ActiveMailbox.messageManager.messages[messageEntryTag];
                    message.isRead = true;
                    viewItem.Font = new Font("Tahoma", 8.25f);
                    showMessage(message);
                }
            }
            //UpdateMailBoxText(ActiveMailbox);
        }
        private void btnDelete_Click(object sender, EventArgs e)
        {

            deletingMessage = new Thread(new ThreadStart(deleting));
            deletingMessage.IsBackground = true;
            deletingMessage.Start();
            
        }
        /// <summary>
        /// delete function
        /// </summary>
        private void deleting()
        {
           
            
            if (this.InvokeRequired)
            {
                NoParaDelegateWorker delegateWorker = new NoParaDelegateWorker(deleting);
                this.BeginInvoke(delegateWorker);
            }
            else
            {
                Hashtable data = new Hashtable();
                lock (this)
                {
                    
                    foreach (ListViewItem viewItem in listMessage.CheckedItems)
                    {

                        string messageEntryTag = (string)viewItem.Tag;
                        Pbdms.BusinessLogic.Mail.Message message = (Pbdms.BusinessLogic.Mail.Message)ActiveMailbox.messageManager.messages[messageEntryTag];
                        if (message != null)
                        {
                            data.Add(message.key, message);
                        }
                    }
                }

                foreach (Pbdms.BusinessLogic.Mail.Message deleMessage in data.Values)
                {
                    ActiveMailbox.messageManager.deleteAMessage(ActiveMailbox, deleMessage);
                }
                updateListView(ActiveMailbox);
                this.Enabled = true;
            }
            
        }
        /// <summary>
        /// reply function
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnReply_Click(object sender, EventArgs e)
        {
            if (mLastViewedListViewItem != null)
            {
                Pbdms.BusinessLogic.Mail.Message message = new Pbdms.BusinessLogic.Mail.Message();
                string id = (string)mLastViewedListViewItem.Tag;

                message = (Pbdms.BusinessLogic.Mail.Message)ActiveMailbox.messageManager.messages[id];
                Pbdms.Forms.Tools.FrmOfflineMsg frmOffline = new Pbdms.Forms.Tools.FrmOfflineMsg();
                
                frmOffline.MdiParent = this.MdiParent;
                try
                {
                    frmOffline.addFriend(message.sender);
                    frmOffline.setSubject("Re:" + message.subject);
                    frmOffline.setText(message.message);
                    frmOffline.Show();
                }
                catch
                {
                    MessageBox.Show("Unable to identity the friend");
                }
                
            }
        }
        /// <summary>
        /// rename all the sender name if the send public key is deleted
        /// </summary>
        /// <param name="keyid"></param>
        public void deleteMessageAssociatedByKeyID(string keyid)
        {
            if (this.InvokeRequired)
            {
                individualDelegateWorker delegateWorker = new individualDelegateWorker(deleteMessageAssociatedByKeyID);
                this.BeginInvoke(delegateWorker, new object[] { keyid });
            }
            else
            {
                lock (this)
                {

                    foreach (ListViewItem viewItem in listMessage.Items)
                    {

                        string messageEntryTag = (string)viewItem.Tag;
                        
                        Pbdms.BusinessLogic.Mail.Message message = (Pbdms.BusinessLogic.Mail.Message)ActiveMailbox.messageManager.messages[messageEntryTag];
                        if (message != null)
                        {
                            if (message.sender.Equals(keyid))
                            {
                                System.Windows.Forms.ListViewItem.ListViewSubItem item=viewItem.SubItems[0];
                                System.Windows.Forms.ListViewItem.ListViewSubItem item1 = viewItem.SubItems[1];
                                item1.Text = keyid;
                            }
                        }
                    }
                }
            }
        }

        public void clear()
        {
            lock(this)
            {
               ActiveMailbox.messageManager.deleteMessages();
               ActiveMailbox = null;
               lastMessageView = null;
               mLastViewedListViewItem = null;
               listMessage.Clear();
              
            }
        }
    }
}